package com.hy.service.impl;


import cn.hutool.core.util.StrUtil;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hy.admin.pojo.SysMenu;
import com.hy.admin.pojo.User;
import com.hy.admin.pojo.vo.AdMenuVo;
import com.hy.helper.MenuHelper;
import com.hy.service.SysMenuService;
import com.hy.util.AuthContextUtil;


import com.hy.util.common.ResultCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import com.hy.mapper.SysMenuMapper;
import lombok.extern.slf4j.Slf4j;
import com.hy.exception.ZhentaoException;
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;



/**
* @author Lenovo
* @description 针对表【sys_menu(菜单表)】的数据库操作Service
* @createDate 2025-03-04 18:50:51
*/
@Service
@Slf4j
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String MENU_CACHE_KEY = "user:menu:";
    private static final long MENU_CACHE_TIME = 30; // 缓存30分钟，可根据实际需要进行调整

    @Override
    public List<AdMenuVo> getMenu() {
        // 获取当前登录用户
        User adUser = AuthContextUtil.get();
        if (adUser == null) {
            log.error("获取菜单失败：用户未登录");
            throw new ZhentaoException(ResultCodeEnum.LOGIN_AUTH, "用户未登录");
        }

        String userId = String.valueOf(adUser.getId());
        // 先从Redis缓存中获取
        String cacheKey = MENU_CACHE_KEY + userId;
        String menuCache = redisTemplate.opsForValue().get(cacheKey);

        // 如果缓存存在，则直接返回
        if (StrUtil.isNotEmpty(menuCache)) {
            log.info("缓存命中 - 用户ID: {}", userId);
            return JSON.parseArray(menuCache, AdMenuVo.class);
        }

        try {
            // 缓存不存在，从数据库获取
            List<SysMenu> adMenu = sysMenuMapper.selectListByUserId(Long.valueOf(userId));
            if (CollectionUtils.isEmpty(adMenu)) {
                log.warn("用户菜单为空 - 用户ID: {}", userId);
                return Collections.emptyList();
            }

            // 构建树形数据
            List<SysMenu> adMenuList = MenuHelper.buildTree(adMenu);
            List<AdMenuVo> menuVoList = this.buildMenus(adMenuList);

            // 将结果存入Redis缓存
            redisTemplate.opsForValue().set(
                    cacheKey,
                    JSON.toJSONString(menuVoList),
                    MENU_CACHE_TIME,
                    TimeUnit.MINUTES
            );

            log.info("菜单加载并缓存 - 用户ID: {}", userId);
            return menuVoList;
        } catch (Exception e) {
            log.error("获取菜单异常 - 用户ID: {}", userId, e);
            throw new ZhentaoException(ResultCodeEnum.SYSTEM_ERROR, "获取菜单失败");
        }
    }

    /**
     * 构建菜单VO列表
     * @param adMenuList 菜单树
     * @return 构建好的菜单VO列表
     */
    private List<AdMenuVo> buildMenus(List<SysMenu> adMenuList) {
        if (CollectionUtils.isEmpty(adMenuList)) {
            return Collections.emptyList();
        }

        List<AdMenuVo> adMenuVoList = new ArrayList<>(adMenuList.size());
        for (SysMenu adMenu : adMenuList) {
            AdMenuVo adMenuVo = new AdMenuVo();
            adMenuVo.setTitle(adMenu.getTitle());
            adMenuVo.setName(adMenu.getComponent());

            // 构建子菜单
            List<SysMenu> children = adMenu.getChildren();
            if (!CollectionUtils.isEmpty(children)) {
                adMenuVo.setChildren(buildMenus(children));
            }
            adMenuVoList.add(adMenuVo);
        }
        return adMenuVoList;
    }

    /**
     * 清除用户菜单缓存
     * @param userId 用户ID
     */
    public void clearUserMenuCache(String userId) {
        String cacheKey = MENU_CACHE_KEY + userId;
        if (redisTemplate.hasKey(cacheKey)) {
            redisTemplate.delete(cacheKey);
            log.info("用户菜单缓存已清除 - 用户ID: {}", userId);
        } else {
            log.info("用户菜单缓存不存在 - 用户ID: {}", userId);
        }
    }

    /**
     * 手动更新用户菜单缓存
     * @param userId 用户ID
     */
    public void refreshUserMenuCache(String userId) {
        try {
            // 从数据库获取菜单并重新缓存
            List<SysMenu> adMenu = sysMenuMapper.selectListByUserId(Long.valueOf(userId));
            if (CollectionUtils.isEmpty(adMenu)) {
                log.warn("用户菜单为空 - 用户ID: {}", userId);
                return;
            }

            // 构建树形数据
            List<SysMenu> adMenuList = MenuHelper.buildTree(adMenu);
            List<AdMenuVo> menuVoList = this.buildMenus(adMenuList);

            // 将新结果存入Redis缓存
            String cacheKey = MENU_CACHE_KEY + userId;
            redisTemplate.opsForValue().set(
                    cacheKey,
                    JSON.toJSONString(menuVoList),
                    MENU_CACHE_TIME,
                    TimeUnit.MINUTES
            );
            log.info("用户菜单缓存已更新 - 用户ID: {}", userId);
        } catch (Exception e) {
            log.error("更新菜单缓存异常 - 用户ID: {}", userId, e);
            throw new ZhentaoException(ResultCodeEnum.SYSTEM_ERROR, "更新菜单缓存失败");
        }
    }
}
